﻿// Copyright (c) Vitaly Kamiansky. All rights reserved. 
// See License.txt in the project root.

using Property.Reloaders;
using Property.Sequences;
using System;
using System.Reactive.Disposables;
using System.Reactive.Linq;

namespace Property
{
    /// <summary>
    /// Contains words that can come immediately after the opening
    /// of a property description.
    /// </summary>
    public static class ReloadableExtensionsReactive
    {
        /// <summary>
        /// ... using observable sequences of the specified form as containers for new values ...
        /// </summary>
        /// <param name="getSequence">I have a function that produces new values for the property. 
        /// Tell me how to turn it into an observable sequence.</param>
        public static ISequenceConveyor<T> Reactive<T>(this Reloadable<T> source, Func<Func<T>,IObservable<T>> getSequence)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (getSequence == null) throw new ArgumentNullException("getSequence");

            return new SourceSequenceConveyor<T>(getSequence);
        }

        /// <summary>
        /// ... using observable sequences as containers for new values ...
        /// </summary>
        public static ISequenceConveyor<T> Reactive<T>(this Reloadable<T> source)
        {
            return source.Reactive(o => Observable.Defer<T>(() => Observable.Return<T>(o())));
        }

        /// <summary>
        /// <para>... synchronously if the call passes through the specified filter (when) ...</para>
        /// <para>( ! ) Don't forget to dispose of what you create with this word.</para>
        /// </summary>
        /// <param name="filter">Tell me how to transform the sequence of reload calls.</param>
        ///  <param name="testMode">Tell me if I have to ignore this word.</param>
        public static IReloaderPrototype<T> Filtered<T>(this Reloadable<T> source, Func<IObservable<object>, IObservable<object>> filter, bool testMode = false)
        {
            return source.Each().Filtered(filter, testMode);
        }

        /// <summary>
        /// <para>... synchronously if the discriminator state passes through the specified sequence filter (when) ...</para>
        /// <para>( ! ) Don't forget to dispose of what you create with this word.</para>
        /// </summary>
        /// <param name="getState">Tell me how the state should be produced 
        /// based on its previous value.</param>
        /// <param name="filter">Tell me how to transform the sequence of reload calls 
        /// represented by the state values.</param>
        /// <param name="testMode">Tell me if I have to ignore this word.</param>
        public static IReloaderPrototype<T> Filtered<T, TState>(this Reloadable<T> source, Func<TState, TState> getState, Func<IObservable<TState>, IObservable<TState>> filter, bool testMode = false)
        {
            return source.Each().Filtered(getState, filter, testMode);
        }
    }
}
